package game.gamestorage.texas.db;

import game.Action;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;

import util.DebugOut;

/**
 * This class is the "db-side" part of the mapping form Java to database</br>
 * Responsable for writing to db
 * 
 * @author Witthold/Korol
 */
public class SetterQueryExecution {

	/** SQLHandler initializes ConnectionManager */
	protected static SQLHandler h = new SQLHandler();


	/**
	 * @category Prequisites<br>
	 *           writes gamedef
	 * @param limited - limited:1; pot-limit:0; no-limit: -1
	 * @param minBet - only int possible
	 * @param maxBet - only int possible
	 * @param num_players -
	 * @param style - cashgame:1; tournament:2; doyle:3;
	 * @param buyin - only int possible
	 * 
	 * @return gamedef_id
	 */
	protected static int registerGameDef(int limited, int minBet, int maxBet, int num_players, int style, int buyin) {
		int gamedef_id = h.sqlGetInt(SetterQuery.selectGameDefID(limited, minBet, maxBet, num_players, style, buyin));
		if (gamedef_id < 0) {
			gamedef_id = h.sqlSetReturnID(SetterQuery.insertGameDef(limited, minBet, maxBet, num_players, style, buyin));
			DebugOut.showVerboseSql("New gamedef with id: " + gamedef_id);
		} else {
			DebugOut.showVerboseSql("Already such a gamedef with id: " + gamedef_id);
		}
		return gamedef_id;
	}


	/**
	 * @category setStartCompetition<br>
	 *           writes player
	 * @param gamedef_id - already generated by db
	 * @return competition_id
	 */
	protected static int registerCompetition(int gamedef_id) {
		int competition_id = h.sqlSetReturnID(SetterQuery.insertCompetition(gamedef_id));

		return competition_id;
	}


	/**
	 * @category setStartCompetition<br>
	 *           writes player - if not already existing
	 * @param player_names - all participants as String[]
	 * @return player_ids
	 */
	protected static int[] registerPlayers(String[] player_names) {
		int[] player_ids = new int[player_names.length];

		HashMap<String, Integer> hm = h.sqlGetHashMapStringInt(SetterQuery.selectPlayerAliasesIDs(player_names));

		for (int i = 0; i < player_ids.length; i++) {
			if (hm.containsKey(player_names[i])) {
				player_ids[i] = hm.get(player_names[i]);
			} else {
				player_ids[i] = h.sqlSetReturnID(SetterQuery.insertPlayer(player_names[i]));
			}
			DebugOut.showVerboseSql(i + ": " + player_ids[i]);
		}

		return player_ids;
	}


	/**
	 * @category setStartCompetition<br>
	 *           writes competition_player<br>
	 *           ids irrelevant: no need for single inserting
	 * @param player_ids already generated by db
	 * @param cash_init - with how much credits do the players start this? -
	 * @param competition_id already generated by db
	 * @return true, if writing to db succeeded
	 */
	protected static boolean registerCompetitionPlayerMap(int[] player_ids, int[] cash_init, int competition_id) {
		DebugOut.showVerboseSql("registerCompetitionPlayerMap");

		if (!h.sqlSet(SetterQuery.insertCompetitionPlayerMap(player_ids, cash_init, competition_id))) {
			return false;
		}

		DebugOut.showVerboseSql("registerCompetitionPlayerMap ok");
		return true;
	}


	/**
	 * @category setHand<br>
	 *           writes hand
	 * @param sb - smallblind
	 * @param bb - bigblind
	 * @param ante - forced bet for all players
	 * @param competition_id already generated by db
	 * @return hand_id
	 */
	protected static int registerHand(int sb, int bb, int ante, int competition_id) {
		int hand_id = h.sqlSetReturnID(SetterQuery.insertHand(sb, bb, ante, competition_id));

		return hand_id;
	}


	/**
	 * @category setHand<br>
	 *           writes hand_player_map
	 * @param position
	 * 			Position of the player in this hand
	 * 			(0: first player behind the button; 1: second player behind the button; ...)
	 * @param cash_init - with how much credits do the players start this? -
	 * @param player_ids already generated by db
	 * @param hand_id already generated by db
	 * @return hand_player_map_ids
	 */
	protected static int[] registerHandPlayerMap(int[] position, int[] cash_init, int[] player_ids, int hand_id) {
		DebugOut.showVerboseSql("registerHandPlayerMap");

		int[] hand_player_map_ids = new int[player_ids.length];
		Arrays.fill(hand_player_map_ids, -1);

		for (int i = 0; i < player_ids.length; i++) {
			if (position[i] > -1) {
				hand_player_map_ids[i] = h.sqlSetReturnID(SetterQuery.insertHandPlayerMap(position[i], cash_init[i], player_ids[i], hand_id));
			}
			DebugOut.showVerboseSql(i + ": " + hand_player_map_ids[i]);
		}

		return hand_player_map_ids;
	}


	/**
	 * @category setHand<br>
	 * @category setEndHand<br>
	 *           writes card_of_player (first bots own, later enemyCards, if available)
	 * @param value of the card (combination of number and suite)
	 * @param hand_player_map_id already generated by db
	 * @return true, if writing to db succeeded
	 */
	protected static boolean registerCardOfPlayer(int value, int hand_player_map_id) {
		if (!h.sqlSet(SetterQuery.insertCardOfPlayer(value, hand_player_map_id))) {
			return false;
		}
		return true;
	}


	/**
	 * @category setEndRound<br>
	 *           writes one round
	 * @param hand_id already generated by db
	 * @param timestamp as unix timestamp
	 * @return round_id
	 */
	protected static int registerRound(int hand_id, long timestamp) {

		int round_id = h.sqlSetReturnID(SetterQuery.insertRound(hand_id, timestamp));

		return round_id;
	}


	/**
	 * @category setEndRound<br>
	 *           writes bets
	 * @param bets - ArrayList of Actions of the players in this round
	 * @param round_id already generated by db
	 * @param player_ids already generated by db
	 * @return true, if writing to db succeeded
	 */
	protected static boolean registerBets(ArrayList<Action> bets, int round_id, int[] player_ids) {

		if (!h.sqlSet(SetterQuery.insertBets(bets, round_id, player_ids))) {
			return false;
		}
		return true;
	}


	/**
	 * @category setEndRound<br>
	 *           writes card_common
	 * @param value of the card (combination of number and suite)
	 * @param round_id already generated by db
	 * @return true, if writing to db succeeded
	 */
	protected static boolean registerCommonCards(int[] value, int round_id) {
		if (!h.sqlSet(SetterQuery.insertCommonCards(value, round_id))) {
			return false;
		}
		return true;
	}


	/**
	 * @category setEndHand<br>
	 *           writes finalpot into hand
	 * @param finalpot - total at the end of the hand
	 * @param hand_id already generated by db
	 * @return true, if writing to db succeeded
	 */
	protected static boolean registerFinalPot(int finalpot, int hand_id) {
		if (!h.sqlSet(SetterQuery.updateFinalPot(finalpot, hand_id))) {
			return false;
		}
		return true;
	}


	/**
	 * @category setEndHand<br>
	 *           writes cash_delta into hand_player_map
	 * @param cash_delta - diff between before and after played hand
	 * @param player_id already generated by db
	 * @param hand_id already generated by db
	 * @return true, if writing to db succeeded
	 */
	protected static boolean registerCashDelta(int cash_delta, int player_id, int hand_id) {
		if (!h.sqlSet(SetterQuery.updateCashDelta(cash_delta, player_id, hand_id))) {
			return false;
		}
		return true;
	}


	/**
	 * @category setEndCompetition<br>
	 *           updates competition_player
	 * @param rank - rank of this player
	 * @param player_id already generated by db
	 * @param competition_id already generated by db
	 * @return true, if writing to db succeeded
	 */
	protected static boolean registerRank(int rank, int player_id, int competition_id) {
		if (!h.sqlSet(SetterQuery.updateRank(rank, player_id, competition_id))) {
			return false;
		}
		return true;
	}


	/**
	 * @return true, if there is at least one connection to the db
	 */
	public static boolean connectionSuccess() {

		return h.connectionSuccess();
	}


	/**
	 * For TESTING only!
	 * 
	 * @param tblName -
	 * @return true, if writing to db succeeded
	 */
	protected static boolean emptyTable(String tblName) {
		if (h.sqlSet(SetterQuery.emptyTable(tblName))) {
			return true;
		}
		return false;
	}
}
